﻿using HB.MsgBusItem;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using System.Linq;
using System.Threading;
using HB.MsgBus.MsgBusItem;

namespace HB.MsgBus
{
    /// <summary>
    /// 观察者模式实现
    /// </summary>
    public class MsgBus
    {
        static MsgBus()
        {
            dic = new ConcurrentDictionary<string, LinkedList<EventRouterItem>>();
            dicSub = new ConcurrentDictionary<string, PermissionsChecker>();
        }
        /// <summary>
        /// 事件委托Topic,事件列表List
        /// </summary>
        static ConcurrentDictionary<string, LinkedList<EventRouterItem>> dic = null;
        /// <summary>
        /// 订阅者id,该订阅者订阅的全部数量count
        /// </summary>
        static ConcurrentDictionary<string, PermissionsChecker> dicSub = null;
        /// <summary>
        /// 发生错误时
        /// </summary>
        public static event Action<Exception> OnError;
        /// <summary>
        /// 单次发布完成时触发
        /// </summary>
        public static event Action<PublishInfo> OnPublishOver;
        /// <summary>
        /// 订阅者执行前事件
        /// </summary>
        public static event Action<PublishInfo> OnPublishDoing;
        static SynchronizationContext MainThread { get; set; }
        /// <summary>
        /// 注册UI线程,必须使用UI线程运行注册，记录UI线程上下文，无耗时
        /// </summary>
        public static void RegsterUIThread()
        {
            MainThread = SynchronizationContext.Current;
            if (MainThread == null)
            {
                throw new Exception("SynchronizationContext NoFound,Please Call in Dispatcher or Control.Invoke");
            }
        }
        #region  订阅核心函数
        static void SubscribeCore<T>(string id, string group, T action, object subscriber = null, bool isExecOnce = false, bool isForceRunOnUI = false, string SubscribeFilePath = null, int SubscribeLineNumber = 0, string SubscriptFunctionName = null) where T : Delegate
        {
            //判定是否async void
            var isVoid = action.Method.ReturnType.Name == "Void";
            bool isAsync = false;
#if NETSTANDARD2_0
              isAsync = action.Method.GetCustomAttributes(typeof(AsyncStateMachineAttribute), false).Length > 0;
#endif
#if NET40
            isAsync = action.Method.GetCustomAttributes(false).Where(zz => zz.GetType().Name == "AsyncStateMachineAttribute").Any();
#endif
            if (isAsync && isVoid)
            {
                throw new Exception("No Support Async Void Delegate,It May Cause Unexpected ControlFlow Error");
            }

            //保证不同次的订阅完整记录

            if (id == null) { id = Guid.NewGuid().ToString(); }
            EventRouterItem ERI = new EventRouterItem() { EventEntity = action, RunOnUIThread = isForceRunOnUI, IsExecOnce = isExecOnce, Group = group, Id = id, SubscribeFilePath = SubscribeFilePath, SubscribeLineNumber = SubscribeLineNumber, SubscribeFunctionName = SubscriptFunctionName };
            WeakReference WR = null;
            if (subscriber != null)
            {
                WR = new WeakReference(subscriber);
            }
            string Topic = typeof(T).FullName;
            if (dic.ContainsKey(Topic))
            {
                var ls = dic[Topic];
                var Note = ls.First;
                while (Note != null)//如果已包含相同id的注册，将其去掉，保证单个id的注册只有一个
                {
                    var Value = Note.Value;
                    if (Value.Id == id)
                    {
                        var temp = Note.Next;
                        ls.Remove(Note);
                        Note = temp; continue;
                    }
                    Note = Note.Next;
                }
                ls.AddLast(ERI);
            }
            else
            {
                LinkedList<EventRouterItem> ls = new LinkedList<EventRouterItem>();
                ls.AddLast(ERI);
                if (!dic.TryAdd(Topic, ls))
                {
                    if (dic.TryGetValue(Topic, out var Link))
                    {
                        Link.AddLast(ERI);
                    }
                }
            }
            //注册权限
            if (!dicSub.ContainsKey(id))
            {
                dicSub.TryAdd(id, new PermissionsChecker());
            }
            dicSub[id].AddOrUpdate(Topic, group, WR);
        }

        #endregion

        #region 常规订阅
        /// <summary>
        /// 订阅事件
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="action">注入T类型的委托</param>
        /// <param name="subscriber">订阅者对象(任意对象)，内部使用弱引用，当对象被回收时，该订阅自动失效，不传则不检查</param>
        /// <param name="SubscribeFilePath">订阅者文件路径，自动生成，无需手动填写</param>
        /// <param name="SubscribeLineNumber">订阅者代码行数，自动生成，无需手动填写</param>
        /// <param name="SubscriptFunctionName">订阅者函数名，自动生成，无需手动填写</param>
        public static void Subscribe<T>(T action, object subscriber = null, [CallerFilePath] string SubscribeFilePath = null, [CallerLineNumber] int SubscribeLineNumber = 0, [CallerMemberName] string SubscriptFunctionName = null) where T : Delegate
        {
            SubscribeByIdGroup<T>(null, null, action, subscriber, SubscribeFilePath, SubscribeLineNumber, SubscriptFunctionName);
        }

        /// <summary>
        /// 强制在UI线程执行订阅，需先RegsterUIThread
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="id">指定此次订阅者的id</param>
        /// <param name="group">指定此次订阅者的分组</param>
        /// <param name="action">注入T类型的委托</param>
        /// <param name="subscriber">订阅者对象(任意对象)，内部使用弱引用，当对象被回收时，该订阅自动失效，不传则不检查</param>
        /// <param name="SubscribeFilePath">订阅者文件路径，自动生成，无需手动填写</param>
        /// <param name="SubscribeLineNumber">订阅者代码行数，自动生成，无需手动填写</param>
        /// <param name="SubscriptFunctionName">订阅者函数名，自动生成，无需手动填写</param>
        public static void SubscribeOnUIThread<T>(T action, string id = null, string group = null, object subscriber = null, [CallerFilePath] string SubscribeFilePath = null, [CallerLineNumber] int SubscribeLineNumber = 0, [CallerMemberName] string SubscriptFunctionName = null) where T : Delegate
        {
            SubscribeCore<T>(id, group, action, subscriber, false, true, SubscribeFilePath, SubscribeLineNumber, SubscriptFunctionName);
        }
        /// <summary>
        /// 订阅
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="id">指定此次订阅者的id</param>
        /// <param name="group">指定此次订阅者的分组</param>
        /// <param name="action">注入T类型的委托</param>
        /// <param name="subscriber">订阅者对象(任意对象)，内部使用弱引用，当对象被回收时，该订阅自动失效，不传则不检查</param>
        /// <param name="SubscribeFilePath">订阅者文件路径，自动生成，无需手动填写</param>
        /// <param name="SubscribeLineNumber">订阅者代码行数，自动生成，无需手动填写</param>
        /// <param name="SubscriptFunctionName">订阅者函数名，自动生成，无需手动填写</param>
        public static void SubscribeByIdGroup<T>(string id, string group, T action, object subscriber = null, [CallerFilePath] string SubscribeFilePath = null, [CallerLineNumber] int SubscribeLineNumber = 0, [CallerMemberName] string SubscriptFunctionName = null) where T : Delegate
        {
            SubscribeCore<T>(id, group, action, subscriber, false, false, SubscribeFilePath, SubscribeLineNumber, SubscriptFunctionName);
        }
        /// <summary>
        /// 只通过id订阅,同一个id的事件只能存在一个
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="id">指定此次订阅者的id</param>
        /// <param name="action">注入T类型的委托</param>
        /// <param name="subscriber">订阅者对象(任意对象)，内部使用弱引用，当对象被回收时，该订阅自动失效，不传则不检查</param>
        /// <param name="SubscribeFilePath">订阅者文件路径，自动生成，无需手动填写</param>
        /// <param name="SubscribeLineNumber">订阅者代码行数，自动生成，无需手动填写</param>
        /// <param name="SubscriptFunctionName">订阅者函数名，自动生成，无需手动填写</param>
        public static void SubscribeById<T>(string id, T action, object subscriber = null, [CallerFilePath] string SubscribeFilePath = null, [CallerLineNumber] int SubscribeLineNumber = 0, [CallerMemberName] string SubscriptFunctionName = null) where T : Delegate
        {
            SubscribeByIdGroup<T>(id, null, action, subscriber, SubscribeFilePath, SubscribeLineNumber, SubscriptFunctionName);
        }
        #endregion



        #region 按模型订阅
        /// <summary>
        /// 按照模型订阅事件
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="action"></param>
        /// <param name="subscriber"></param>
        /// <param name="SubscribeFilePath"></param>
        /// <param name="SubscribeLineNumber"></param>
        /// <param name="SubscriptFunctionName"></param>
        public static void Subscribe<T>(Action<T> action, object subscriber = null, [CallerFilePath] string SubscribeFilePath = null, [CallerLineNumber] int SubscribeLineNumber = 0, [CallerMemberName] string SubscriptFunctionName = null) where T : class
        {
            SubscribeByIdGroup<Action<T>>(null, null, action, subscriber, SubscribeFilePath, SubscribeLineNumber, SubscriptFunctionName);
        }
        /// <summary>
        /// 按照id订阅
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="id"></param>
        /// <param name="action"></param>
        /// <param name="subscriber"></param>
        /// <param name="SubscribeFilePath"></param>
        /// <param name="SubscribeLineNumber"></param>
        /// <param name="SubscriptFunctionName"></param>
        public static void SubscribeById<T>(string id, Action<T> action, object subscriber = null, [CallerFilePath] string SubscribeFilePath = null, [CallerLineNumber] int SubscribeLineNumber = 0, [CallerMemberName] string SubscriptFunctionName = null) where T : class
        {
            SubscribeByIdGroup<Action<T>>(id, null, action, subscriber, SubscribeFilePath, SubscribeLineNumber, SubscriptFunctionName);
        }
        /// <summary>
        /// 订阅到UI线程
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="action"></param>
        /// <param name="id"></param>
        /// <param name="group"></param>
        /// <param name="subscriber"></param>
        /// <param name="SubscribeFilePath"></param>
        /// <param name="SubscribeLineNumber"></param>
        /// <param name="SubscriptFunctionName"></param>
        public static void SubscribeOnUIThread<T>(Action<T> action, string id = null, string group = null, object subscriber = null, [CallerFilePath] string SubscribeFilePath = null, [CallerLineNumber] int SubscribeLineNumber = 0, [CallerMemberName] string SubscriptFunctionName = null) where T : class
        {
            SubscribeCore<Action<T>>(id, group, action, subscriber, false, true, SubscribeFilePath, SubscribeLineNumber, SubscriptFunctionName);
        }
        /// <summary>
        /// 通过id和分组订阅
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="id"></param>
        /// <param name="group"></param>
        /// <param name="action"></param>
        /// <param name="subscriber"></param>
        /// <param name="SubscribeFilePath"></param>
        /// <param name="SubscribeLineNumber"></param>
        /// <param name="SubscriptFunctionName"></param>
        public static void SubscribeByIdGroup<T>(string id, string group, Action<T> action, object subscriber = null, [CallerFilePath] string SubscribeFilePath = null, [CallerLineNumber] int SubscribeLineNumber = 0, [CallerMemberName] string SubscriptFunctionName = null) where T : class
        {
            SubscribeCore<Action<T>>(id, group, action, subscriber, false, false, SubscribeFilePath, SubscribeLineNumber, SubscriptFunctionName);
        }
        #endregion
        /// <summary>
        /// 修改订阅者的指定topic所属组
        /// </summary>
        /// <param name="id">订阅者id</param>
        /// <param name="newGroup">新分组</param>
        public static void ChangeGroup<T>(string id, string newGroup)
        {
            if (dicSub.ContainsKey(id))
            {
                string topic = typeof(T).FullName;
                dicSub[id].AddOrUpdate(topic, newGroup, null);
            }
        }
        /// <summary>
        /// 修改订阅者的所有所属组
        /// </summary>
        /// <param name="id">订阅者id</param>
        /// <param name="newGroup">新分组</param>
        public static void ChangeGroup(string id, string newGroup)
        {
            if (dicSub.ContainsKey(id))
            {
                dicSub[id].UpdateAll(newGroup);
            }
        }
        /// <summary>
        /// 发布基类，同步方法
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="group">null为不指定</param>
        /// <param name="id">null为不指定</param>
        /// <param name="invoteParam">委托调用，如 t=>t(1,2)</param>
        /// <param name="publishFilePath">调用发布的文件,自动生成，无需手动填写</param>
        /// <param name="publishLineNumber">调用发布的代码行数,自动生成，无需手动填写</param>
        /// <param name="publishFunctionName">调用发布的函数名,自动生成，无需手动填写</param>
        private static void PublishBase<T>(string group, string id, Action<Delegate> invoteParam, string publishFilePath, int publishLineNumber, string publishFunctionName) where T : Delegate
        {
            string Topic = typeof(T).FullName;
            lock (TopicLocker.GetLock(Topic))
            {
                if (dic.ContainsKey(Topic))
                {
                    var LinkLs = dic[Topic];
                    var Note = LinkLs.First;
                    bool ExecFlat = true;
                    int execCount = 0;
                    while (Note != null)
                    {
                        var Value = Note.Value;
                        bool Enabled = dicSub.ContainsKey(Value.Id) && dicSub[Value.Id].IsEnabled(Topic);//不存在不可用
                        PermissionsChecker subChecker = null;
                        if (Enabled)
                        {
                            subChecker = dicSub[Value.Id];
                            string newGroup = subChecker.GetNewGroup(Topic);
                            if (newGroup != Value.Group)
                            {
                                Value.Group = newGroup;//运行中修改分组
                            }
                        }
                        if (!Enabled)//不可用则移除回调
                        {
                            var tempNote = Note.Next;
                            LinkLs.Remove(Note);
                            dicSub.TryRemove(Value.Id, out var v);//移除权限
                            Note = tempNote;
                            continue;
                        }
                        else
                        {
                            ExecFlat = group == null ? true : Value.Group == group;
                            if (ExecFlat)
                            {
                                ExecFlat = id == null ? true : Value.Id == id;
                            }

                            if (ExecFlat)
                            {
                                PublishInfo pi = null;
                                if (OnPublishDoing != null || OnPublishOver != null)
                                {


                                    pi = new PublishInfo()
                                    {
                                        DelegateName = Topic,
                                        PublishFilePath = publishFilePath,
                                        PublishFunctionName = publishFunctionName,
                                        PublishLineNumber = publishLineNumber,
                                        Group = Value.Group,
                                        Id = Value.Id,
                                        IsExecOnce = Value.IsExecOnce,
                                        RunOnUIThread = Value.RunOnUIThread,
                                        SubscribeFilePath = Value.SubscribeFilePath,
                                        SubscribeFunctionName = Value.SubscribeFunctionName,
                                        SubscribeLineNumber = Value.SubscribeLineNumber
                                    };
                                }
                                OnPublishDoing?.Invoke(pi);
                                execCount++;
                                try
                                {
                                    if (Value.RunOnUIThread)
                                    {
                                        if (MainThread == null)
                                        {
                                            throw new Exception("Please Run RegsterUIThread First");
                                        }
                                        //发送到UI线程来执行
                                        MainThread.Send(new SendOrPostCallback(s =>
                                        {
                                            invoteParam.Invoke(Value.EventEntity);
                                        }), null);
                                    }
                                    else
                                    {
                                        invoteParam.Invoke(Value.EventEntity);
                                    }

                                    if (Value.IsExecOnce)
                                    {
                                        ClearSubscription<T>(Value.Id);
                                    }
                                }
                                catch (Exception ex)
                                {
                                    if (pi != null)
                                    {
                                        pi.Exception = ex;
                                    }
                                    OnError?.Invoke(ex);
                                    if (OnError == null)
                                    {
                                        System.Diagnostics.Debug.WriteLine(ex.Message);
                                        System.Diagnostics.Debug.WriteLine($"File:{Value.SubscribeFilePath},LineNumber:{Value.SubscribeLineNumber},FunctionName:{Value.SubscribeFunctionName}");
                                    }
                                }
                                OnPublishOver?.Invoke(pi);
                            }
                        }
                        Note = Note.Next;
                    }

                }
            }
        }
        #region 同步方法
        /// <summary>
        /// 同步发布（当前线程执行）
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="condition"></param>
        /// <param name="invoteParam">委托调用，如 t=>t(1,2)</param>
        /// <param name="callBack">结果回调</param>
        /// <param name="publishFilePath">调用发布的文件,自动生成，无需手动填写</param>
        /// <param name="publishLineNumber">调用发布的代码行数,自动生成，无需手动填写</param>
        /// <param name="publishFunctionName">调用发布的函数名,自动生成，无需手动填写</param>
        public static void PublishIf<T>(bool condition, Action<T> invoteParam, Action<int> callBack = null, [CallerFilePath] string publishFilePath = null, [CallerLineNumber] int publishLineNumber = 0, [CallerMemberName] string publishFunctionName = null) where T : Delegate
        {
            if (condition)
            {
                PublishByGroupId<T>(null, null, invoteParam, callBack, publishFilePath, publishLineNumber, publishFunctionName);
            }
        }
        /// <summary>
        /// 同步发布（当前线程执行）
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="invoteParam">委托调用，如 t=>t(1,2)</param>
        /// <param name="callBack">结果回调</param>
        /// <param name="publishFilePath">调用发布的文件,自动生成，无需手动填写</param>
        /// <param name="publishLineNumber">调用发布的代码行数,自动生成，无需手动填写</param>
        /// <param name="publishFunctionName">调用发布的函数名,自动生成，无需手动填写</param>
        public static void Publish<T>(Action<T> invoteParam, Action<int> callBack = null, [CallerFilePath] string publishFilePath = null, [CallerLineNumber] int publishLineNumber = 0, [CallerMemberName] string publishFunctionName = null) where T : Delegate
        {
            PublishByGroupId<T>(null, null, invoteParam, callBack, publishFilePath, publishLineNumber, publishFunctionName);
        }
        /// <summary>
        /// 以模型同步发布
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="invoteParam"></param>
        /// <param name="callBack"></param>
        /// <param name="publishFilePath"></param>
        /// <param name="publishLineNumber"></param>
        /// <param name="publishFunctionName"></param>
        public static void Publish<T>(T invoteParam, Action<int> callBack = null, [CallerFilePath] string publishFilePath = null, [CallerLineNumber] int publishLineNumber = 0, [CallerMemberName] string publishFunctionName = null) where T : class
        {
            PublishByGroupId<Action<T>>(null, null, t => t(invoteParam), callBack, publishFilePath, publishLineNumber, publishFunctionName);
        }
        /// <summary>
        /// 同步发布（当前线程执行）
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="condition"></param>
        /// <param name="group">null为不指定</param>
        /// <param name="id">null为不指定</param>
        /// <param name="invoteParam">委托调用，如 t=>t(1,2)</param>
        /// <param name="callBack">结果回调</param>
        /// <param name="publishFilePath">调用发布的文件,自动生成，无需手动填写</param>
        /// <param name="publishLineNumber">调用发布的代码行数,自动生成，无需手动填写</param>
        /// <param name="publishFunctionName">调用发布的函数名,自动生成，无需手动填写</param>
        public static void PublishByGroupIdIf<T>(bool condition, string group, string id, Action<T> invoteParam, Action<int> callBack = null, [CallerFilePath] string publishFilePath = null, [CallerLineNumber] int publishLineNumber = 0, [CallerMemberName] string publishFunctionName = null) where T : Delegate
        {
            if (condition)
            {
                int Count = 0;
                object locker = 0;
                PublishBase<T>(group, id, Source =>
                {
                    invoteParam.Invoke((T)Source);
                    lock (locker)
                    {
                        Count++;
                    }
                }, publishFilePath, publishLineNumber, publishFunctionName);
                callBack?.Invoke(Count);
            }
        }
        /// <summary>
        /// 同步发布
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="condition"></param>
        /// <param name="group"></param>
        /// <param name="id"></param>
        /// <param name="invoteParam"></param>
        /// <param name="callBack"></param>
        /// <param name="publishFilePath"></param>
        /// <param name="publishLineNumber"></param>
        /// <param name="publishFunctionName"></param>
        public static void PublishByGroupIdIf<T>(bool condition, string group, string id, T invoteParam, Action<int> callBack = null, [CallerFilePath] string publishFilePath = null, [CallerLineNumber] int publishLineNumber = 0, [CallerMemberName] string publishFunctionName = null) where T : class
        {
            PublishByGroupIdIf<Action<T>>(condition, group, id, t => t(invoteParam), callBack, publishFilePath, publishLineNumber, publishFunctionName);
        }

        /// <summary>
        /// 同步发布（当前线程执行）
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="group">null为不指定</param>
        /// <param name="id">null为不指定</param>
        /// <param name="invoteParam">委托调用，如 t=>t(1,2)</param>
        /// <param name="callBack">结果回调</param>
        /// <param name="publishFilePath">调用发布的文件,自动生成，无需手动填写</param>
        /// <param name="publishLineNumber">调用发布的代码行数,自动生成，无需手动填写</param>
        /// <param name="publishFunctionName">调用发布的函数名,自动生成，无需手动填写</param>
        public static void PublishByGroupId<T>(string group, string id, Action<T> invoteParam, Action<int> callBack = null, [CallerFilePath] string publishFilePath = null, [CallerLineNumber] int publishLineNumber = 0, [CallerMemberName] string publishFunctionName = null) where T : Delegate
        {
            int Count = 0;
            object locker = 0;
            PublishBase<T>(group, id, Source =>
            {
                invoteParam.Invoke((T)Source);
                lock (locker)
                {
                    Count++;
                }
            }, publishFilePath, publishLineNumber, publishFunctionName);
            callBack?.Invoke(Count);
        }
        /// <summary>
        /// 同步发布
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="group"></param>
        /// <param name="id"></param>
        /// <param name="invoteParam"></param>
        /// <param name="callBack"></param>
        /// <param name="publishFilePath"></param>
        /// <param name="publishLineNumber"></param>
        /// <param name="publishFunctionName"></param>
        public static void PublishByGroupId<T>(string group, string id, T invoteParam, Action<int> callBack = null, [CallerFilePath] string publishFilePath = null, [CallerLineNumber] int publishLineNumber = 0, [CallerMemberName] string publishFunctionName = null) where T : class
        {
            PublishByGroupId<Action<T>>(group, id, t => t(invoteParam), callBack, publishFilePath, publishLineNumber, publishFunctionName);
        }
        /// <summary>
        /// 同步发布并返回（当前线程执行）
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="T2"></typeparam>
        /// <param name="invoteParam">委托调用，如 t=>t(1,2)</param>
        /// <param name="publishFilePath">调用发布的文件,自动生成，无需手动填写</param>
        /// <param name="publishLineNumber">调用发布的代码行数,自动生成，无需手动填写</param>
        /// <param name="publishFunctionName">调用发布的函数名,自动生成，无需手动填写</param>
        /// <returns></returns>
        public static List<T2> PublishForResult<T, T2>(Func<T, T2> invoteParam, [CallerFilePath] string publishFilePath = null, [CallerLineNumber] int publishLineNumber = 0, [CallerMemberName] string publishFunctionName = null) where T : Delegate
        {
            List<T2> Ls = new List<T2>();
            PublishBase<T>(null, null, Source =>
            {
                T2 tem = invoteParam.Invoke((T)Source);
                Ls.Add(tem);
            }, publishFilePath, publishLineNumber, publishFunctionName);
            return Ls;
        }
        /// <summary>
        /// 同步发布并返回（当前线程执行）
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="T2"></typeparam>
        /// <param name="group">null为不指定</param>
        /// <param name="id">null为不指定</param>
        /// <param name="invoteParam">委托调用，如 t=>t(1,2)</param>
        /// <param name="publishFilePath">调用发布的文件,自动生成，无需手动填写</param>
        /// <param name="publishLineNumber">调用发布的代码行数,自动生成，无需手动填写</param>
        /// <param name="publishFunctionName">调用发布的函数名,自动生成，无需手动填写</param>
        /// <returns></returns>
        public static List<T2> PublishForResultByGroupId<T, T2>(string group, string id, Func<T, T2> invoteParam, [CallerFilePath] string publishFilePath = null, [CallerLineNumber] int publishLineNumber = 0, [CallerMemberName] string publishFunctionName = null) where T : Delegate
        {
            List<T2> Ls = new List<T2>();
            PublishBase<T>(group, id, Source =>
            {
                T2 tem = invoteParam.Invoke((T)Source);
                Ls.Add(tem);
            }, publishFilePath, publishLineNumber, publishFunctionName);
            return Ls;
        }

        #endregion

        #region 异步
        /// <summary>
        /// 异步发布返回
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="T2"></typeparam>
        /// <param name="group">null为不指定</param>
        /// <param name="id">null为不指定</param>
        /// <param name="invoteParam">委托调用，如 t=>t(1,2)</param>
        /// <param name="asyncCallBack">结果回调</param>
        /// <param name="publishFilePath">调用发布的文件,自动生成，无需手动填写</param>
        /// <param name="publishLineNumber">调用发布的代码行数,自动生成，无需手动填写</param>
        /// <param name="publishFunctionName">调用发布的函数名,自动生成，无需手动填写</param>
        public static Task PublishAsyncForResultByGroupId<T, T2>(string group, string id, Func<T, T2> invoteParam, Action<List<T2>> asyncCallBack = null, [CallerFilePath] string publishFilePath = null, [CallerLineNumber] int publishLineNumber = 0, [CallerMemberName] string publishFunctionName = null) where T : Delegate
        {
            List<T2> Ls = new List<T2>();
            return Task.Factory.StartNew(() =>
               {
                   PublishBase<T>(group, id, Source =>
                   {
                       T2 tem = invoteParam.Invoke((T)Source);
                       Ls.Add(tem);
                   }, publishFilePath, publishLineNumber, publishFunctionName);
               }).ContinueWith(t =>
               {
                   asyncCallBack.Invoke(Ls);
               });
        }
        /// <summary>
        /// 异步发布发布返回
        /// </summary>
        /// <typeparam name="T">委托类型</typeparam>
        /// <typeparam name="T2">返回值类型</typeparam>
        /// <param name="group">null为不指定</param>
        /// <param name="id">null为不指定</param>
        /// <param name="invoteParam">委托调用，如 t=>t(1,2)</param>
        /// <param name="publishFilePath">调用发布的文件,自动生成，无需手动填写</param>
        /// <param name="publishLineNumber">调用发布的代码行数,自动生成，无需手动填写</param>
        /// <param name="publishFunctionName">调用发布的函数名,自动生成，无需手动填写</param>
        /// <returns></returns>
        public static Task<List<T2>> PublishAsyncForResultByGroupId<T, T2>(string group, string id, Func<T, T2> invoteParam, [CallerFilePath] string publishFilePath = null, [CallerLineNumber] int publishLineNumber = 0, [CallerMemberName] string publishFunctionName = null) where T : Delegate
        {
            List<T2> Ls = new List<T2>();
            return Task.Factory.StartNew(() =>
                {
                    PublishBase<T>(group, id, Source =>
                    {
                        T2 tem = invoteParam.Invoke((T)Source);
                        Ls.Add(tem);
                    }, publishFilePath, publishLineNumber, publishFunctionName);
                    return Ls;
                });
        }
        /// <summary>
        /// 异步发布返回
        /// </summary>
        /// <typeparam name="T">委托类型</typeparam>
        /// <typeparam name="T2">返回值类型</typeparam>
        /// <param name="invoteParam">委托调用，如 t=>t(1,2)</param>
        /// <param name="asyncCallBack">结果回调</param>
        /// <param name="publishFilePath">调用发布的文件,自动生成，无需手动填写</param>
        /// <param name="publishLineNumber">调用发布的代码行数,自动生成，无需手动填写</param>
        /// <param name="publishFunctionName">调用发布的函数名,自动生成，无需手动填写</param>
        public static Task PublishAsyncForResult<T, T2>(Func<T, T2> invoteParam, Action<List<T2>> asyncCallBack = null, [CallerFilePath] string publishFilePath = null, [CallerLineNumber] int publishLineNumber = 0, [CallerMemberName] string publishFunctionName = null) where T : Delegate
        {
            return PublishAsyncForResultByGroupId<T, T2>(null, null, invoteParam, asyncCallBack, publishFilePath, publishLineNumber, publishFunctionName);
        }
        /// <summary>
        /// 异步发布返回
        /// </summary>
        /// <typeparam name="T">委托类型</typeparam>
        /// <typeparam name="T2">返回值类型</typeparam>
        /// <param name="invoteParam">委托调用，如 t=>t(1,2)</param>
        /// <param name="publishFilePath">调用发布的文件,自动生成，无需手动填写</param>
        /// <param name="publishLineNumber">调用发布的代码行数,自动生成，无需手动填写</param>
        /// <param name="publishFunctionName">调用发布的函数名,自动生成，无需手动填写</param>
        /// <returns></returns>
        public static Task<List<T2>> PublishAsyncForResult<T, T2>(Func<T, T2> invoteParam, [CallerFilePath] string publishFilePath = null, [CallerLineNumber] int publishLineNumber = 0, [CallerMemberName] string publishFunctionName = null) where T : Delegate
        {
            return PublishAsyncForResultByGroupId<T, T2>(null, null, invoteParam, publishFilePath, publishLineNumber, publishFunctionName);
        }
        /// <summary>
        /// 异步发布（后台线程执行）
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="group">null为不指定</param>
        /// <param name="id">null为不指定</param>
        /// <param name="invoteParam"></param>
        /// <param name="asyncCallBack"></param>
        /// <param name="publishFilePath">调用发布的文件,自动生成，无需手动填写</param>
        /// <param name="publishLineNumber">调用发布的代码行数,自动生成，无需手动填写</param>
        /// <param name="publishFunctionName">调用发布的函数名,自动生成，无需手动填写</param>
        public static Task PublishAsyncByGroupId<T>(string group, string id, Action<T> invoteParam, Action<int> asyncCallBack = null, [CallerFilePath] string publishFilePath = null, [CallerLineNumber] int publishLineNumber = 0, [CallerMemberName] string publishFunctionName = null) where T : Delegate
        {
            return Task.Factory.StartNew(() =>
             {
                 PublishByGroupId(group, id, invoteParam, asyncCallBack, publishFilePath, publishLineNumber, publishFunctionName);
             });
        }
        /// <summary>
        /// 异步发布
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="group"></param>
        /// <param name="id"></param>
        /// <param name="invoteParam"></param>
        /// <param name="asyncCallBack"></param>
        /// <param name="publishFilePath"></param>
        /// <param name="publishLineNumber"></param>
        /// <param name="publishFunctionName"></param>
        /// <returns></returns>
        public static Task PublishAsyncByGroupId<T>(string group, string id, T invoteParam, Action<int> asyncCallBack = null, [CallerFilePath] string publishFilePath = null, [CallerLineNumber] int publishLineNumber = 0, [CallerMemberName] string publishFunctionName = null) where T : class
        {
            return PublishAsyncByGroupId<Action<T>>(group, id, t => t(invoteParam), asyncCallBack, publishFilePath, publishLineNumber, publishFunctionName);
        }

        /// <summary>
        /// 异步发布（后台线程执行）
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="condition"></param>
        /// <param name="group">null为不指定</param>
        /// <param name="id">null为不指定</param>
        /// <param name="invoteParam"></param>
        /// <param name="asyncCallBack"></param>
        /// <param name="publishFilePath">调用发布的文件,自动生成，无需手动填写</param>
        /// <param name="publishLineNumber">调用发布的代码行数,自动生成，无需手动填写</param>
        /// <param name="publishFunctionName">调用发布的函数名,自动生成，无需手动填写</param>
        public static Task PublishAsyncByGroupIdIf<T>(bool condition, string group, string id, Action<T> invoteParam, Action<int> asyncCallBack = null, [CallerFilePath] string publishFilePath = null, [CallerLineNumber] int publishLineNumber = 0, [CallerMemberName] string publishFunctionName = null) where T : Delegate
        {
            if (condition)
            {
                return Task.Factory.StartNew(() =>
                             {
                                 PublishByGroupId(group, id, invoteParam, asyncCallBack, publishFilePath, publishLineNumber, publishFunctionName);
                             });
            }
            return new Task(() => { });

        }
        /// <summary>
        /// 异步发布
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="condition"></param>
        /// <param name="group"></param>
        /// <param name="id"></param>
        /// <param name="invoteParam"></param>
        /// <param name="asyncCallBack"></param>
        /// <param name="publishFilePath"></param>
        /// <param name="publishLineNumber"></param>
        /// <param name="publishFunctionName"></param>
        /// <returns></returns>
        public static Task PublishAsyncByGroupIdIf<T>(bool condition, string group, string id, T invoteParam, Action<int> asyncCallBack = null, [CallerFilePath] string publishFilePath = null, [CallerLineNumber] int publishLineNumber = 0, [CallerMemberName] string publishFunctionName = null) where T : class
        {
            return PublishAsyncByGroupIdIf<Action<T>>(condition, group, id, t => t(invoteParam), asyncCallBack, publishFilePath, publishLineNumber, publishFunctionName);

        }
        /// <summary>
        /// 异步发布（后台线程执行）
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="invoteParam"></param>
        /// <param name="asyncCallBack"></param>
        /// <param name="publishFilePath">调用发布的文件,自动生成，无需手动填写</param>
        /// <param name="publishLineNumber">调用发布的代码行数,自动生成，无需手动填写</param>
        /// <param name="publishFunctionName">调用发布的函数名,自动生成，无需手动填写</param> 

        public static Task PublishAsync<T>(Action<T> invoteParam, Action<int> asyncCallBack = null, [CallerFilePath] string publishFilePath = null, [CallerLineNumber] int publishLineNumber = 0, [CallerMemberName] string publishFunctionName = null) where T : Delegate
        {
            return Task.Factory.StartNew(() => { Publish(invoteParam, asyncCallBack, publishFilePath, publishLineNumber, publishFunctionName); });
        }
        /// <summary>
        /// 异步发布（模型）
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="invoteParam"></param>
        /// <param name="asyncCallBack"></param>
        /// <param name="publishFilePath"></param>
        /// <param name="publishLineNumber"></param>
        /// <param name="publishFunctionName"></param>
        /// <returns></returns>
        public static Task PublishAsync<T>(T invoteParam, Action<int> asyncCallBack = null, [CallerFilePath] string publishFilePath = null, [CallerLineNumber] int publishLineNumber = 0, [CallerMemberName] string publishFunctionName = null) where T : class
        {
            return PublishAsync<Action<T>>(t => t(invoteParam), asyncCallBack, publishFilePath, publishLineNumber, publishFunctionName);
        }
        /// <summary>
        /// 异步发布（后台线程执行）
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="condition"></param>
        /// <param name="invoteParam"></param>
        /// <param name="asyncCallBack"></param>
        /// <param name="publishFilePath">调用发布的文件,自动生成，无需手动填写</param>
        /// <param name="publishLineNumber">调用发布的代码行数,自动生成，无需手动填写</param>
        /// <param name="publishFunctionName">调用发布的函数名,自动生成，无需手动填写</param>
        public static Task PublishAsyncIf<T>(bool condition, Action<T> invoteParam, Action<int> asyncCallBack = null, [CallerFilePath] string publishFilePath = null, [CallerLineNumber] int publishLineNumber = 0, [CallerMemberName] string publishFunctionName = null) where T : Delegate
        {
            if (condition)
            {
                return Task.Factory.StartNew(() => { Publish(invoteParam, asyncCallBack, publishFilePath, publishLineNumber, publishFunctionName); });
            }
            return new Task(() => { });
        }
        /// <summary>
        /// 异步发布(模型)
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="condition"></param>
        /// <param name="invoteParam"></param>
        /// <param name="asyncCallBack"></param>
        /// <param name="publishFilePath"></param>
        /// <param name="publishLineNumber"></param>
        /// <param name="publishFunctionName"></param>
        /// <returns></returns>
        public static Task PublishAsyncIf<T>(bool condition, T invoteParam, Action<int> asyncCallBack = null, [CallerFilePath] string publishFilePath = null, [CallerLineNumber] int publishLineNumber = 0, [CallerMemberName] string publishFunctionName = null) where T : class
        {
            return PublishAsyncIf<Action<T>>(condition, t => t(invoteParam), asyncCallBack, publishFilePath, publishLineNumber, publishFunctionName);

        }
        #endregion
        /// <summary>
        /// 清理该id所有的订阅，将在运行时判定清理。
        /// </summary>
        /// <param name="id"></param>
        public static void ClearSubscription(string id)
        {
            if (id == null) { return; }
            if (dicSub.ContainsKey(id))
            {
                dicSub[id].Clear();
            }
        }
        /// <summary>
        /// 按委托清理指定T  topic的订阅，将在运行时判定清理。
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="id"></param>
        public static void ClearSubscription<T>(string id) where T : Delegate
        {
            if (id == null) { return; }
            string topic = typeof(T).FullName;
            if (dicSub.ContainsKey(id))
            {
                dicSub[id].Remove(topic);
            }
        }
        /// <summary>
        /// 按模型清理指定T  topic的订阅，将在运行时判定清理。
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="id"></param>
        public static void ClearSubscriptionC<T>(string id) where T : class
        {
            ClearSubscription<Action<T>>(id);
        }
        /// <summary>
        /// 获取指定topic的订阅者群,按委托
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public static List<EventRouterItemBase> GetSubscriptActicedPoints<T>() where T : Delegate
        {
            var key = typeof(T).FullName;
            return GetSubscriptActicedPoints(key);
        }
        /// <summary>
        /// 获取指定topic的订阅者群,按模型
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public static List<EventRouterItemBase> GetSubscriptActicedPointsC<T>() where T : class
        {
            var key = typeof(Action<T>).FullName;
            return GetSubscriptActicedPoints(key);
        }
        /// <summary>
        /// 获取指定topic的订阅者群
        /// </summary>
        /// <param name="topicFullName">T的fullName</param>
        /// <returns></returns>
        public static List<EventRouterItemBase> GetSubscriptActicedPoints(string topicFullName)
        {
            lock (TopicLocker.GetLock(topicFullName))
            {
                if (dic.ContainsKey(topicFullName))
                {
                    return dic[topicFullName].Where(zz => dicSub.ContainsKey(zz.Id) && dicSub[zz.Id].IsEnabled(topicFullName)).Select(zz => (EventRouterItemBase)zz).ToList();
                }
            }
            return new List<EventRouterItemBase>(0);
        }
        /// <summary>
        /// 获取已激活的topic列表
        /// </summary>
        /// <returns></returns>
        public static List<string> GetSubscribeActicedTopics()
        {
            return dic.Keys.ToList();
        }
    }
}
